package derbyclnt.sockets;

import derbyclnt.*;
import static derbyclnt.Logger.*;
import derbyclnt.inter.*;
import derbyclnt.messages.*;
import derbyclnt.messages.MessageTypesProtos.MessageTypes;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.google.protobuf.InvalidProtocolBufferException;

public abstract class MessageProcessor {
	public static Map<MessageTypes, MessageProcessor> registerMessageProcessors() {
		HashMap<MessageTypes, MessageProcessor> messageProcessors = new HashMap<MessageTypes, MessageProcessor>();
		
		messageProcessors.put(MessageTypes.MESSAGE_HELLO, new HelloMessageProcessor());
		messageProcessors.put(MessageTypes.MESSAGE_CAR, new CarMessageProcessor());
		
		return messageProcessors;
	}
	
	abstract void Process(MainManager mgr, RawData raw);
}

class HelloMessageProcessor extends MessageProcessor {

	@Override
	void Process(MainManager mgr, RawData raw) {
		try {
			assert raw.getType() == MessageTypes.MESSAGE_HELLO; // TODO 
			assert mgr.getClientId() == -1;
			HelloProtos.Hello hello = HelloProtos.Hello.parseFrom(raw.getData());
			logi("From server: " + hello.getText());
			logd("Client ID = " + hello.getClientId());
			mgr.setClientId(hello.getClientId());
		} catch (InvalidProtocolBufferException e) {
			loge(e.getMessage());
		}
	}
	
}


class CarMessageProcessor extends MessageProcessor {

	@Override
	void Process(MainManager mgr, RawData raw) {
		if (mgr.getClientId() == -1)
			return;
		try {
			CarProtos.Car car = CarProtos.Car.parseFrom(raw.getData());
			assert car.getClientId() >= 0;
			
			if (car.getClientId() == mgr.getClientId()) {
				updateCar(car, mgr.getCar());
			}
			else 
			{
				// add a new car if it doesn't exist
				ICar c = mgr.getEngine().getOtherCar(car.getClientId());
				if (c == null)
				{
					c = mgr.getEngine().addOtherCar(car.getClientId());
					assert c != null;
				}
				updateCar(car, c);
			}	
		} catch (InvalidProtocolBufferException e) {
			loge(e.getMessage());
		}
	}
	
	private void updateCar (CarProtos.Car msg, ICar car)
	{
		assert msg.getClientId() == car.getClientId();
		car.setFaceAngle(msg.getFaceAngle());
		car.setMoveAngle(msg.getMoveAngle());
		car.setPosX(msg.getPosX());
		car.setPosY(msg.getPosY());
		car.setVelocity(msg.getVelocity());
	}
	
}
